Logic Apps/ciso-reporting/ciso-incidents-summary-man.yaml (264 lines of code) (raw):

Descriptor: Name: CisoIncidentsSummary DisplayName: CISO Incidents Summary Description: Skills to get a summary view on the status of the incidents in Defender SupportedAuthTypes: - ApiKey Authorization: Type: APIKey Key: sig Location: QueryParams AuthScheme: '' SkillGroups: - Format: API Settings: OpenApiSpecUrl: <YOUR-REPO-URL>/ciso-incidents-summary-api-spec.yaml - Format: KQL Skills: - Name: CisoIncidentsStatusSummary DisplayName: CISO - Incidents Status Summary Description: Get a summary of the incidents status in Defender DescriptionForModel : Get a summary of the incidents status in Defender. If severities are specified in the prompt (e.g. High and Medium), concatenate them as a comma separated list of double-quoted strings with the first letter in uppercase (like "High","Medium"). If start date and end date are not specified, consider the last 7 days. If the top number of results is not specified, consider 5 incidents titles. If csv_of_severities is not specified, consider only "High". Inputs: - Name: start_date Description: The first date of the considered time window Required: true - Name: end_date Description: The end date of the considered time window Required: true - Name: top_results_number Description: The number of top incidents to be considered Required: true - Name: csv_of_severities Description: Comma separated list of severities. E.g. "High","Medium" Required: true Settings: Target: Defender Template: |- let start_time = datetime({{start_date}}); let end_time = datetime({{end_date}}); let top_incs_number = int({{top_results_number}}); let severities = dynamic([{{csv_of_severities}}]); let top_incidents = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where Severity in (severities) and CreatedTime between (start_time .. end_time) | extend SecInc = strcat("[",Severity,"] ",Title) | summarize TotalCount = count() by SecInc | top top_incs_number by TotalCount; let closed_incidents = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where Severity in (severities) and not(isnull(ClosedTime)) and CreatedTime between (start_time .. end_time) | extend SecInc = strcat("[",Severity,"] ",Title) | summarize ClosedCount = count() by SecInc; let classified_incidents = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where Severity in (severities) and CreatedTime between (start_time .. end_time) | extend SecInc = strcat("[",Severity,"] ",Title) | summarize BenignPositiveCount = countif(Classification == "BenignPositive"), FalsePositiveCount = countif(Classification == "FalsePositive"), TruePositiveCount = countif(Classification == "TruePositive"), UndeterminedCount = countif(Classification == "Undetermined") by SecInc; top_incidents | join kind=leftouter (closed_incidents) on SecInc | join kind=leftouter (classified_incidents) on SecInc | project SecInc, TotalCount, ClosedCount, BenignPositiveCount, FalsePositiveCount, TruePositiveCount, UndeterminedCount | order by TotalCount desc, ClosedCount desc, TruePositiveCount desc - Name: CisoTruePositiveIncidentsTTAnalysis DisplayName: CISO - True Positive Incidents Tactics and Techniques Analysis Description: Get a summary of the tactics and techniques used in the incidents that were classified as true positives DescriptionForModel : Get a summary of the tactics and techniques used in the incidents that were classified as true positives If severities are specified in the prompt (e.g. High and Medium), concatenate them as a comma separated list of double-quoted strings with the first letter in uppercase (like "High","Medium"). If start date and end date are not specified, consider the last 7 days. If severities is not specified, consider only "High". Inputs: - Name: start_date Description: The first date of the considered time window Required: true - Name: end_date Description: The end date of the considered time window Required: true - Name: csv_of_severities Description: Comma separated list of severities. E.g. "High","Medium" Required: true Settings: Target: Defender Template: |- let start_time = datetime({{start_date}}); let end_time = datetime({{end_date}}); let severities = dynamic([{{csv_of_severities}}]); SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where Severity in (severities) and CreatedTime between (start_time .. end_time) | where Classification == "TruePositive" | extend SecInc = strcat("[",Severity,"] ",Title) | extend AdditionalDataParsed = parse_json(AdditionalData) | summarize Occurrences=count(), Tactics=make_set(AdditionalDataParsed.tactics), Techniques=make_set(AdditionalDataParsed.techniques) by SecInc | order by Occurrences desc - Name: CisoMTTR DisplayName: CISO - Get Mean Time To Resolve (MTTR) Description: Calculate the Mean Time To Resolve (MTTR), in minutes, of the incidents closed in the specified period and compare it to its value in the previous month DescriptionForModel : Calculate the Mean Time To Resolve (MTTR), in minutes, for incidents closed within the specified period and compare it to the MTTR from the entire previous month. The MTTR is defined as the average time between the creation and closure of incidents, for the incidents closed within the specified time window. If the start and / or end dates are not specified, consider as time window the last 7 days. The response is a table that includes the MTTR in the specified time window, the MTTR in the previous month, the percentage variation between the two MTTR values, the first day of the specified time window, the last day of the specified time window, the first day of the previous month, and the last day of the previous month. Inputs: - Name: start_date Description: The first date of the considered time window Required: true - Name: end_date Description: The end date of the considered time window Required: true Settings: Target: Defender Template: |- let start_time = datetime({{start_date}}); let end_time = datetime({{end_date}}); let lastMonthStart = startofmonth(datetime_add('month', -1, now())); let lastMonthEnd = endofmonth(datetime_add('month', -1, now())); let timeWindowMTTR = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where ClosedTime between (start_time .. end_time) | extend ResolveTime = datetime_diff('minute', ClosedTime, CreatedTime) | summarize MTTR = round(avg(ResolveTime),0) | extend j = "forcedjoin" | project timeWindowMTTR = MTTR, j; let lastMonthMTTR = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where CreatedTime between (lastMonthStart .. lastMonthEnd) | extend ResolveTime = datetime_diff('minute', ClosedTime, CreatedTime) | summarize MTTR = round(avg(ResolveTime),0) | extend j = "forcedjoin" | project lastMonthMTTR = MTTR, j; timeWindowMTTR | join lastMonthMTTR on j | extend PercentageChange = round(((timeWindowMTTR - lastMonthMTTR) * 100.0 / lastMonthMTTR), 0) | project timeWindowMTTR, lastMonthMTTR, PercentageChange, start_time, end_time, lastMonthStart, lastMonthEnd - Name: CisoMTTA DisplayName: CISO - Get Mean Time To Acknowledge (MTTA) Description: Calculate the Mean Time To Acknowledge (MTTA), in minutes, of the incidents created in the specified period and compare it to its value in the previous month DescriptionForModel : Calculate the Mean Time To Acknowledge (MTTA), in minutes, for incidents created in the specified period and compare it to the MTTA from the entire previous month. The MTTA is defined as the average time between the creation and first modification of incidents, for the incidents created within the specified time window. If the start and / or end dates are not specified, consider as time window the last 7 days. The response is a table that includes the MTTA in the specified time window, the MTTA in the previous month, the percentage variation between the two MTTA values, the first day of the specified time window, the last day of the specified time window, the first day of the previous month, and the last day of the previous month. Inputs: - Name: start_date Description: The first date of the considered time window Required: true - Name: end_date Description: The end date of the considered time window Required: true Settings: Target: Defender Template: |- let start_time = datetime({{start_date}}); let end_time = datetime({{end_date}}); let lastMonthStart = startofmonth(datetime_add('month', -1, now())); let lastMonthEnd = endofmonth(datetime_add('month', -1, now())); let timeWindowMTTA = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where CreatedTime between (start_time .. end_time) | extend AcknowledgmentTime = datetime_diff('minute', FirstModifiedTime, CreatedTime) | where isnotnull(AcknowledgmentTime) | summarize MTTA = round(avg(AcknowledgmentTime), 0) | extend j = "forcedjoin" | project timeWindowMTTA = MTTA, j; let lastMonthMTTA = SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where CreatedTime between (lastMonthStart .. lastMonthEnd) | extend AcknowledgmentTime = datetime_diff('minute', FirstModifiedTime, CreatedTime) | where isnotnull(AcknowledgmentTime) | summarize MTTA = round(avg(AcknowledgmentTime), 0) | extend j = "forcedjoin" | project lastMonthMTTA = MTTA, j; timeWindowMTTA | join lastMonthMTTA on j | extend PercentageChange = round(((timeWindowMTTA - lastMonthMTTA) * 100.0 / lastMonthMTTA), 0) | project timeWindowMTTA, lastMonthMTTA, PercentageChange, start_time, end_time, lastMonthStart, lastMonthEnd - Name: CisoIncidentsOwners DisplayName: CISO - Get Top Incident Owners Description: Get the list of top owners for the incidents created in the specified period DescriptionForModel : Get the list of top owners for the incidents created in the specified period. If the start and / or end dates are not specified, consider as time window the last 7 days. If the number of top owners is not specified, consider the top 10 owners. Inputs: - Name: start_date Description: The first date of the considered time window Required: true - Name: end_date Description: The end date of the considered time window Required: true - Name: top_owners_number Description: The number of top owners to be considered Required: true Settings: Target: Defender Template: |- let start_time = datetime({{start_date}}); let end_time = datetime({{end_date}}); let top_owners_number = int({{top_owners_number}}); SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where CreatedTime between (start_time .. end_time) | where isnotempty(Owner) | extend OwnerUPN = tostring(parse_json(Owner).userPrincipalName) | where isnotempty(OwnerUPN) | summarize IncidentCount = count() by OwnerUPN | top top_owners_number by IncidentCount | project OwnerUPN, IncidentCount | order by IncidentCount desc - Name: CisoMostImpactedUsers DisplayName: CISO - Get Most Impacted Users Description: Get the list of the users impacted by the biggest number of alerts related to incidents created in the specified period and not closed as 'false positive' DescriptionForModel : Get the list of the users impacted by the biggest number of alerts related to incidents created in the specified period and not closed as 'false positive'. If the start and / or end dates are not specified, consider as time window the last 7 days. If the number of top impacted users is not specified, consider the top 10 impacted users. Inputs: - Name: start_date Description: The first date of the considered time window Required: true - Name: end_date Description: The end date of the considered time window Required: true - Name: top_impacted_users_number Description: The number of top impacted users to be considered Required: true Settings: Target: Defender Template: |- let start_time = datetime({{start_date}}); let end_time = datetime({{end_date}}); let top_owners_number = int({{top_impacted_users_number}}); SecurityIncident | summarize arg_max(TimeGenerated, *) by IncidentName | where Status <> "Closed" or not(Status == "Closed" and Classification == "Undetermined" and ModifiedBy == "Microsoft XDR" ) | where CreatedTime between (start_time .. end_time) and Classification <> "FalsePositive" | mv-expand AlertIds | extend aid = tostring(AlertIds) | join kind=inner SecurityAlert on $left.aid == $right.SystemAlertId | project aid, Entities | extend Entities = parse_json(Entities) | mv-expand Entities | where not(isempty(Entities.UserPrincipalName)) | distinct aid, UserPrincipalName = tostring(Entities.UserPrincipalName) | summarize AlertNumber = count() by UserPrincipalName | order by AlertNumber desc, UserPrincipalName | top {{top_impacted_users_number}} by AlertNumber